package com.xhj.bigfactory.bigFactory.threadCommunication;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import static java.lang.System.out;
import static java.lang.Thread.currentThread;

/**
 * -
 *
 * @author 周沫 @Date 2021-07-30 @Time 2:14
 */
public class ThreadCommunicationDemo {

  static class Data {

    private AtomicInteger integer = new AtomicInteger(0);

    private int number = 0;
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void increment() {
      lock.lock();
      while (number == 0) {
        try {
          condition.await();
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
        }
      }
      number++;
      out.println(number);
      condition.signalAll();
      lock.unlock();
    }

    public void decrement() {
      lock.lock();
      while (number == 1) {
        try {
          condition.await();
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
        }
      }
      number--;
      out.println(number);
      condition.signalAll();
      lock.unlock();
    }
  }

  static class Data2 {

    private AtomicInteger integer = new AtomicInteger(0);

    private int number = 0;
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void increment() {
      lock.lock();
      try {
        while (number == 1) {
          condition.await();
        }
        number++;
        out.println("number = " + number);
        condition.signalAll();
      } catch (Exception e) {

      } finally {
        lock.unlock();
      }
    }

    public void decrement() {
      lock.lock();
      try {
        while (number == 0) {
          condition.await();
        }
        number--;
        out.println("number = " + number);
        condition.signalAll();
      } catch (Exception e) {

      } finally {
        lock.unlock();
      }
    }
  }

  static class Data66 {

    private AtomicInteger integer = new AtomicInteger(0);
    private AtomicInteger integer2 = new AtomicInteger(0);

    private int number = 0;
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void increment() {
      synchronized (integer) {
        while (number == 1) {
          integer2.notify();
        }
        if (number == 0) number++;
      }
      try {
        integer.notify();
        integer.wait();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    public void decrement() {
      synchronized (integer2) {
        while (number == 1) {
          integer.notify();
        }
        if (number == 1) number--;
      }
      try {
        integer2.wait();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

  static class Data4 {

    private AtomicInteger integer = new AtomicInteger(0);

    private int number = 0;
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void increment() {
      lock.lock();
      try {
        if (number == 1) {
          condition.await();
        }
        number++;
        out.println("number = " + number);
        condition.signalAll();
      } catch (Exception e) {

      } finally {
        lock.unlock();
      }
    }

    public void decrement() {
      lock.lock();
      try {
        if (number == 0) {
          condition.await();
        }
        number--;
        out.println("number = " + number);
        condition.signalAll();
      } catch (Exception e) {

      } finally {
        lock.unlock();
      }
    }
  }

  static class Data3 {

    private AtomicInteger integer = new AtomicInteger(0);

    private int number = 0;
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void increment() {
      lock.lock();
      try {
        while (number == 1) {
          lock.unlock();
        }
        number++;
        out.println("number = " + number);
      } catch (Exception e) {
      } finally {
        lock.unlock();
      }
    }

    public void decrement() {
      lock.lock();
      try {
        while (number == 0) {
          lock.unlock();
        }
        number--;
      } catch (Exception e) {

      } finally {
        lock.unlock();
      }
    }
  }

  public static void main(String[] args) {
    Data4 data = new Data4();
    new Thread(
            () -> {
              out.println(currentThread().getName() + ": come in...");
              for (int i = 0; i < 5; i++) {
                data.increment();
              }
            },
            "AAA")
        .start();
    new Thread(
            () -> {
              out.println(currentThread().getName() + ": come in...");
              for (int i = 0; i < 5; i++) {
                data.decrement();
              }
            },
            "BBB")
        .start();
  }
}
